package com.hyt.it.ogt.api.pj;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.core.util.FastJsonUtil;
import com.hyt.core.util.StringUtils;
import com.hyt.it.ogt.common.config.ApiVersionConstant;
import com.hyt.it.ogt.common.config.GlobalVariable;
import com.hyt.it.ogt.controller.base.BaseController;
import com.hyt.it.ogt.pj.common.Constants;
import com.hyt.it.ogt.pj.common.MarkException;
import com.hyt.it.ogt.pj.common.ResponseCode;
import com.hyt.it.ogt.pj.enums.ProjectPtBindingStatusEnums;
import com.hyt.it.ogt.pj.model.dto.pj.PjProjectCandidatePushDTO;
import com.hyt.it.ogt.pj.model.entity.Project;
import com.hyt.it.ogt.pj.model.entity.TotalScore;
import com.hyt.it.ogt.pj.model.param.ProjectInfoParam;
import com.hyt.it.ogt.pj.model.param.ProjectStudentsSubjectScoreParam;
import com.hyt.it.ogt.pj.model.vo.ItemScoreVo;
import com.hyt.it.ogt.pj.model.vo.ProjectNewVo;
import com.hyt.it.ogt.pj.model.vo.StudentMarkStatus;
import com.hyt.it.ogt.pj.model.vo.StudentSubjectSubjectiveScore;
import com.hyt.it.ogt.pj.service.*;
import com.hyt.loginfo.model.User;
import com.hyt.model.PageParam;
import com.hyt.swagger.ApiVersion;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@ApiSort(value = 24)
@Api(tags = "24.评卷对外接口", value = "评卷对外接口")
@RestController
@RequestMapping("markApi")
@Slf4j
public class MarkApi extends BaseController {

    @Autowired
    private ITotalScoreService totalScoreService;

    @Autowired
    private IItemScoreService itemScoreService;

    @Autowired
    private ISubjectScoreService subjectScoreService;

    @Autowired
    private IProjectService iProjectService;

    @Autowired
    private IMarkDataCacheService iMarkDataCacheService;

    @Autowired
    private IProjectDfyhService projectDfyhService;

    @Autowired
    private ICommonAutomaticAllocationService commonAutomaticAllocationService;

    @Autowired
    private GlobalVariable globalVariable;

    @ApiOperationSort(value = 1)
    @ApiOperation(value = "24.1查询成绩", notes = Constants.SWAGGER_METHOD_NOTES)
    @GetMapping("getGrade")
    public ApiResponse<List<TotalScore>> getGrade(@RequestParam String projectId) {
        List<TotalScore> totalScores = totalScoreService.getGrade(projectId);
        return ApiResponse.<List<TotalScore>>builder()
                .code(ResponseCode.SUCCESS)
                .data(totalScores)
                .build();
    }

    @ApiOperationSort(value = 2)
    @ApiOperation(value = "24.2获取单个考生的小题得分", notes = "20000:获取成功,20101:成绩为空")
    @GetMapping("getStudentItemScore")
    public ApiResponse<List<ItemScoreVo>> getStudentItemScore(@RequestParam String projectId, @RequestParam String admissionNum) {
        List<ItemScoreVo> itemScores = itemScoreService.getStudentItemScore(projectId, admissionNum);
        return ApiResponse.<List<ItemScoreVo>>builder()
                .data(itemScores)
                .code(ResponseCode.SUCCESS)
                .build();
    }

    @ApiOperationSort(value = 3)
    @ApiOperation(value = "24.3获取单个考生的主观分和评卷状态", notes = "20000:获取成功,20111:成绩为空")
    @GetMapping("getStudentSubjectScore")
    public ApiResponse<StudentMarkStatus> getStudentSubjectScore(@RequestParam String projectId, @RequestParam String admissionNum) {
        logger.info("## 查询考生的项目id:{},考生的准考证:{}", projectId, admissionNum);
        StudentMarkStatus studentMarkStatus = subjectScoreService.selectStudentMarkStatus(projectId, admissionNum);
        logger.info("## 获取单个考生的主观分和评卷状态数据:{}", JSONObject.toJSONString(studentMarkStatus));
        return ApiResponse.<StudentMarkStatus>builder()
                .data(studentMarkStatus)
                .code(ResponseCode.SUCCESS)
                .build();
    }

    @ApiOperationSort(value = 4)
    @ApiOperation(value = "24.4获取考试任务所有考生的主观分和评卷状态", notes = "20000:获取成功,20111:成绩为空")
    @GetMapping("getAllStudentSubjectScore")
    public ApiResponse<Map<String, StudentMarkStatus>> getAllStudentSubjectScore(@RequestParam String projectId) {
        Map<String, StudentMarkStatus> studentMarkStatusMap = subjectScoreService.selectAllStudentMarkStatus(projectId);
        logger.info("## 获取考试任务所有考生的主观分和评卷状态数据:{}", JSONObject.toJSONString(studentMarkStatusMap));
        return ApiResponse.<Map<String, StudentMarkStatus>>builder()
                .data(studentMarkStatusMap)
                .code(ResponseCode.SUCCESS)
                .build();
    }

    @ApiOperationSort(value = 5)
    @ApiOperation(value = "24.5撤销考生评卷", notes = "20000:取消成功, 20401:撤销考生评卷失败")
    @GetMapping("repealCandidateMark")
    public Object repealCandidateMark(@RequestParam String projectId, @RequestParam String admissionNums) {
        try {
            if (StringUtils.isEmpty(admissionNums)) {
                return ApiResponse.builder()
                        .code(ResponseCode.ADMISSIONNUMS_NULL)
                        .build();
            } else {
                iProjectService.repealCandidateMark(projectId, admissionNums);
                //return ApiResponse.builder().code(ResponseCode.SUCCESS).build();
                return ApiResponse.builder().code(ResponseCode.SUCCESS).build();
            }
        } catch (Exception e) {
            log.error("# 撤销考生评卷失败:", e);
            return ApiResponse.builder().code(ResponseCode.REPEAL_CANDIDATE_MARK_ERROR).build();
        }
    }

    @ApiOperationSort(value = 6)
    @ApiOperation(value = "24.6推送获取评卷数据通知", notes = "20000:成功, 20406:推送评卷数据失败, 20405:推送评卷数据失败异常")
    @PostMapping("pushMarkData")
    public Object pushMarkData(@RequestParam String examId, @RequestParam String officeId) {
        log.info("# 推送评卷数据参数 ： {} {}", examId, officeId);
        try {
            boolean succeed = iMarkDataCacheService.replaceIntoCache(examId, officeId);
            if (succeed) {
                return ApiResponse.builder()
                        .code(ResponseCode.SUCCESS)
                        .build();
            } else {
                return ApiResponse.builder()
                        .code(ResponseCode.PUSH_MARK_DATA_FAIL)
                        .build();
            }
        } catch (Exception e) {
            log.error("# 推送评卷数据异常:", e);
            return ApiResponse.builder()
                    .code(ResponseCode.PUSH_MARK_DATA_EXCEPTION)
                    .build();
        }
    }

    @ApiOperationSort(value = 7)
    @ApiOperation(value = "24.7 更新评卷项目信息", notes = "20000:成功, 20407:更新评卷项目信息异常, 20408:评卷项目信息为空")
    @PutMapping("updateProjectInfo")
    public Object updateProjectInfo(@RequestBody ProjectInfoParam projectInfoParam) {
        log.info("# 更新评卷项目信息参数 ： {}", projectInfoParam.toString());
        try {
            //更新评卷项目信息
            iProjectService.updateProjectInfo(projectInfoParam);
            return ApiResponse.builder()
                    .code(ResponseCode.SUCCESS)
                    .build();
        } catch (Exception e) {
            log.error("# 更新评卷项目信息异常:", e);
            return ApiResponse.builder()
                    .code(ResponseCode.UPDATE_PROJECT_INFO_EXCEPTION)
                    .build();
        }
    }

    @ApiOperationSort(value = 8)
    @ApiOperation(value = "24.8 推送评卷任务", notes = "20000:成功")
    @PostMapping("pushMarkTask")
    public Object pushMarkTask(@RequestParam String paramJson) throws Exception {
        log.info("# pushMarkTask推送评卷任务参数:{}", paramJson);
        try {
            JSONObject param = JSONObject.parseObject(paramJson);
            String projectId = (String) param.get("examId");
            String officeId = (String) param.get("officeId");
            Project project = iProjectService.getById(projectId);
            if (project != null && project.getIsInit()) {
                //评卷项目已经初始化过，直接获取增量评卷数据
                iProjectService.addProjectStudent(projectId, officeId);
            } else {
                //评卷项目未初始化，开始初始化评卷项目
                iProjectService.initProject(projectId, officeId);
            }

            // 删除没有主观题的所有同步信息
            iProjectService.deleteNotSubjectiveSubject(projectId);

            // 自动分配任务
            commonAutomaticAllocationService.commonAutomaticAllocation(projectId);
            return ApiResponse.builder()
                    .code(ResponseCode.SUCCESS)
                    .build();
        } catch (MarkException markException) {
            return ApiResponse.builder()
                    .code(Integer.parseInt(markException.getMessage()))
                    .build();
        } catch (Exception e) {
            log.error("# 查询是否允许推送异常:", e);
            return ApiResponse.builder()
                    .code(ResponseCode.KW_MARK_PUSH_CHECK_EXCEPTION)
                    .build();
        }
    }

    @ApiOperationSort(value = 9)
    @ApiOperation(value = "24.9 查询是否允许推送（现考现评）", notes = "20000:成功;")
    @PostMapping("projectPushCheck/{examId}")
    public ApiResponse<Object> projectPushCheck(@PathVariable("examId") String examId) {
        log.debug("# 查询是否允许推送参数 ： {}", examId);
        try {
            projectDfyhService.projectPushCheck(examId);
            return ApiResponse.builder()
                    .code(ResponseCode.SUCCESS)
                    .build();
        } catch (MarkException markException) {
            return ApiResponse.builder()
                    .code(Integer.parseInt(markException.getMessage()))
                    .build();
        } catch (Exception e) {
            log.error("# 查询是否允许推送异常:", e);
            return ApiResponse.builder()
                    .code(ResponseCode.KW_MARK_PUSH_CHECK_EXCEPTION)
                    .build();
        }
    }


    @ApiOperationSort(value = 10)
    @ApiOperation(value = "24.10 接收考务推送过来各种数据（现考现评）", notes = "20000:成功;")
    @ApiVersion(group = ApiVersionConstant.V2_4_10)
    @PostMapping("projectDataPush")
    public ApiResponse<Object> projectDataPush(@RequestBody PjProjectCandidatePushDTO pjProjectCandidatePushDTO) {
        log.debug("# 接收考务推送过来各种数据:{} ", JSON.toJSON(pjProjectCandidatePushDTO));
        try {
            projectDfyhService.projectDataPush(pjProjectCandidatePushDTO);
            // 自动分配任务
            String projectId = pjProjectCandidatePushDTO.getPjProjectInfoDTO().getBatchId();
            commonAutomaticAllocationService.commonAutomaticAllocation(projectId);
            return ApiResponse.builder()
                    .code(ResponseCode.SUCCESS)
                    .build();
        } catch (MarkException markException) {
            return ApiResponse.builder()
                    .code(Integer.parseInt(markException.getMessage()))
                    .build();
        } catch (Exception e) {
            log.error("# 接收考务推送过来各种数据异常:", e);
            return ApiResponse.builder()
                    .code(ResponseCode.KW_MARK_PUSH_EXCEPTION)
                    .build();
        }
    }

    @ApiOperationSort(value = 11)
    @ApiOperation(value = "24.11 查询是否允许修改考试类型并删除数据", notes = "20000:成功;")
    @PostMapping("examTypeChangeCheck/{examId}")
    public ApiResponse<Object> examTypeChangeCheck(@PathVariable("examId") String examId) {
        log.debug("# 查询是否允许修改考试类型并删除数据参数 ： {}", examId);
        try {
            projectDfyhService.examTypeChangeCheck(examId);
            return ApiResponse.builder()
                    .code(ResponseCode.SUCCESS)
                    .build();
        } catch (MarkException markException) {
            return ApiResponse.builder()
                    .code(Integer.parseInt(markException.getMessage()))
                    .build();
        } catch (Exception e) {
            log.error("# 查询是否允许修改考试类型并删除数据异常:", e);
            return ApiResponse.builder()
                    .code(ResponseCode.KW_EXAM_TYPE_CHANGE_EXCEPTION)
                    .build();
        }
    }

    @ApiOperationSort(value = 12)
    @ApiOperation(value = "24.12 获取评卷路径", notes = "20000:成功;")
    @PostMapping("getMarkPath")
    public ApiResponse<Object> getMarkPath() {
        return ApiResponse.builder()
                .data(globalVariable.getMarkPath())
                .code(ResponseCode.SUCCESS)
                .build();
    }

    @ApiOperationSort(value = 13)
    @ApiOperation(value = "24.13获取批量考生的主观分和评卷状态", notes = "20000:获取成功,20111:成绩为空")
    @PostMapping("getStudentsSubjectScore")
    public ApiResponse<List<StudentSubjectSubjectiveScore>> getStudentsSubjectScore(@RequestBody ProjectStudentsSubjectScoreParam projectStudentsSubjectScoreParam) {
        logger.info("## 查询考生客观题总分参数:{}", FastJsonUtil.getBeanToJson(projectStudentsSubjectScoreParam));
        List<StudentSubjectSubjectiveScore> studentMarkStatus = new ArrayList<>();
        if (null == projectStudentsSubjectScoreParam || StringUtils.isEmpty(projectStudentsSubjectScoreParam.getProjectId()) || CollUtil.isEmpty(projectStudentsSubjectScoreParam.getAdmissionNums())) {
            return ApiResponse.<List<StudentSubjectSubjectiveScore>>builder()
                    .data(studentMarkStatus)
                    .code(ResponseCode.SUCCESS)
                    .build();
        }
        studentMarkStatus = subjectScoreService.selectStudentsMarkStatus(projectStudentsSubjectScoreParam.getProjectId(), projectStudentsSubjectScoreParam.getAdmissionNums());
        logger.info("## 获取单个考生的主观分和评卷状态数据:{}", FastJsonUtil.getBeanToJson(studentMarkStatus));
        return ApiResponse.<List<StudentSubjectSubjectiveScore>>builder()
                .data(studentMarkStatus)
                .code(ResponseCode.SUCCESS)
                .build();
    }

    /**************************************************【平台相关接口】*********************************************************************/
    @ApiOperationSort(value = 21)
    @ApiOperation(value = "24.21 获取评卷项目列表", notes = "20000:成功;51242101: 获取不到当前登录人信息, 51242102: 项目绑定状态参数不合法")
    @ApiImplicitParams({
            @ApiImplicitParam(
                    name = "current", value = "当前分页的页码", dataType = "Integer", paramType = "query", required = true
            ),
            @ApiImplicitParam(
                    name = "size", value = "当前分页的数据条数", dataType = "Integer", paramType = "query", required = true
            ),
            @ApiImplicitParam(
                    name = "projectName", value = "项目名称", dataType = "String", paramType = "query"
            ),
            @ApiImplicitParam(
                    name = "markStatus", value = "评卷状态【0:未开始，1:评卷中，2:已完成】", dataType = "Integer", paramType = "query"
            ),
            @ApiImplicitParam(
                    name = "classfication", value = "考试类型【0：无考场，1：虚拟考场，2：现考现评】", dataType = "Integer", paramType = "query"
            ),
            @ApiImplicitParam(
                    name = "bindingStatus", value = "项目的绑定状态", dataType = "Integer", paramType = "query"
            )
    })
    @RequestMapping(value = "pt/getProjectByPage", method = RequestMethod.GET)
    public ApiResponse<Page<ProjectNewVo>> getProjectByPage(
            @RequestParam(value = "current", required = true) Integer current,
            @RequestParam(value = "size", required = true) Integer size,
            @RequestParam(value = "projectName", required = false) String projectName,
            @RequestParam(value = "markStatus", required = false) Integer markStatus,
            @RequestParam(value = "classfication", required = false) Integer classfication,
            @RequestParam(value = "bindingStatus", required = false) Integer bindingStatus,
            @RequestParam(value = "projectDataType", required = false) Integer projectDataType) {
        User loginUser = getCurrentUser();
        if (null == loginUser) {
            return ApiResponse.<Page<ProjectNewVo>>builder()
                    .code(51242101)
                    .build();
        }
        if (null != bindingStatus) {
            ProjectPtBindingStatusEnums projectPtBindingStatusEnums = ProjectPtBindingStatusEnums.getEnumsByStatus(bindingStatus);
            if (null == projectPtBindingStatusEnums) {
                return ApiResponse.<Page<ProjectNewVo>>builder()
                        .code(51242102)
                        .build();
            }
        }
        String officeId = loginUser.getOfficeid();
        PageParam<ProjectNewVo> pageParam = new PageParam<ProjectNewVo>();
        pageParam.setCurrent(current);
        pageParam.setSize(size);
        return ApiResponse.<Page<ProjectNewVo>>builder()
                .code(ResponseCode.SUCCESS)
                .data(projectDfyhService.page(pageParam, projectName, markStatus, officeId, classfication, bindingStatus, projectDataType))
                .build();
    }


    @ApiOperationSort(value = 22)
    @ApiOperation(value = "24.22 获取评卷项目详情", notes = "20000:成功;51242201: 获取不到当前登录人信息, 51242202: 项目绑定状态参数不合法")
    @ApiImplicitParams({
            @ApiImplicitParam(
                    name = "projectId", value = "评卷项目id", dataType = "String", paramType = "query", required = true
            )
    })
    @RequestMapping(value = "pt/getProjectById", method = RequestMethod.GET)
    public ApiResponse<ProjectNewVo> getProjectById(@RequestParam(value = "projectId", required = true) String projectId) {
        User loginUser = getCurrentUser();
        if (null == loginUser) {
            return ApiResponse.<ProjectNewVo>builder()
                    .code(51242201)
                    .build();
        }
        return ApiResponse.<ProjectNewVo>builder()
                .code(ResponseCode.SUCCESS)
                .data(projectDfyhService.getProjectNewVoById(projectId, loginUser.getOfficeid()))
                .build();
    }


    @ApiOperationSort(value = 23)
    @ApiOperation(value = "24.23 批量获取多评卷项目详情", notes = "20000:成功;51242301: 获取不到当前登录人信息, 51242302: 项目绑定状态参数不合法")
    @ApiImplicitParams({
            @ApiImplicitParam(
                    name = "projectIds", value = "评卷项目ids,多个项目以逗号[,]分割", dataType = "String", paramType = "query", required = true
            )
    })
    @RequestMapping(value = "pt/getProjectByIds", method = RequestMethod.GET)
    public ApiResponse<List<ProjectNewVo>> getProjectByIds(@RequestParam(value = "projectIds", required = true) String projectIds) {
        User loginUser = getCurrentUser();
        if (null == loginUser) {
            return ApiResponse.<List<ProjectNewVo>>builder()
                    .code(51242301)
                    .build();
        }
        return ApiResponse.<List<ProjectNewVo>>builder()
                .code(ResponseCode.SUCCESS)
                .data(projectDfyhService.getProjectNewVoByIds(projectIds, loginUser.getOfficeid()))
                .build();
    }


    @ApiOperationSort(value = 24)
    @ApiOperation(value = "24.24 修改评卷项目平台绑定状态", notes = "20000:成功;51242401: 获取不到当前登录人信息, 51242402: 项目绑定状态参数不合法")
    @ApiImplicitParams({
            @ApiImplicitParam(
                    name = "projectId", value = "评卷项目id", dataType = "String", paramType = "query", required = true
            ),
            @ApiImplicitParam(
                    name = "bindingStatus", value = "项目的绑定状态【0: 取消绑定，1:已绑定】", dataType = "Integer", paramType = "query", required = true
            )
    })
    @RequestMapping(value = "pt/updateProjectPtBindingStatus", method = RequestMethod.GET)
    public ApiResponse<Boolean> updateProjectPtBindingStatus(
            @RequestParam(value = "projectId", required = true) String projectId,
            @RequestParam(value = "bindingStatus", required = true) Integer bindingStatus) {
        User loginUser = getCurrentUser();
        if (null == loginUser) {
            return ApiResponse.<Boolean>builder()
                    .code(51242401)
                    .build();
        }
        if (null != bindingStatus) {
            ProjectPtBindingStatusEnums projectPtBindingStatusEnums = ProjectPtBindingStatusEnums.getEnumsByStatus(bindingStatus);
            if (null == projectPtBindingStatusEnums) {
                return ApiResponse.<Boolean>builder()
                        .code(51242402)
                        .build();
            }
        }
        return ApiResponse.<Boolean>builder()
                .code(ResponseCode.SUCCESS)
                .data(projectDfyhService.updateProjectPtBindingStatus(projectId, bindingStatus))
                .build();
    }

    @ApiOperationSort(value = 25)
    @ApiOperation(value = "24.25 批量获取考生的小题得分", notes = "20000:获取成功,20101:成绩为空")
    @GetMapping("getStudentItemScoreByAdmissionNums")
    public ApiResponse<List<ItemScoreVo>> getStudentItemScoreByAdmissionNums(@RequestParam String projectId, @RequestParam List<String> admissionNums) {
        List<ItemScoreVo> itemScores = itemScoreService.getStudentItemScoreByAdmissionNums(projectId, admissionNums);
        return ApiResponse.<List<ItemScoreVo>>builder()
                .data(itemScores)
                .code(ResponseCode.SUCCESS)
                .build();
    }

}
